#!/usr/bin/env node
'use strict'

// const path = require('path')
const fs = require('fs')
const XLSX = require('xlsx')

const Pzip = require('pizzip')
const Docxtemplater = require('docxtemplater')
const expressions = require('docxtemplater/expressions.js')
const { compile } = require('docxtemplater/expressions.js')
const ImageModule = require('@baitic/docxtemplater-image-module')
const ImageDocxtemplater = require('@baitic/docxtemplater')
const log = require('./utils/log')
const pkg = require('./package.json')
const pathExistsSync = require('path-exists').sync
const { Command } = require('commander')
const { globSync } = require('glob')

expressions.filters.where = function (input, query) {
  return input.filter(function (item) {
    return compile(query)(item)
  })
}

const program = new Command()
const COMMANDS = {
  EXECL_TO_JOSN: 'jsonbyxlsx',
  CREATE_BY_JSON: 'createbyjson',
  CREATE_BY_XLSX: 'createbyxlsx',
  IMAGE_BY_DIR: 'imagebydir',
  PARSE_IMAGE: 'parseImage',
  MERGE_DATA: 'mergedata',
}
const EXTENSION = {
  json: '.json',
  docx: '.docx',
}

function main() {
  registerCommands()
}
main()
function registerCommands() {
  program
    .name(Object.keys(pkg.bin)[0])
    .command(COMMANDS.EXECL_TO_JOSN)
    .description('将xlsx文件转换为json文件')
    .requiredOption('-i, --input <file>', '输入一个.xlsx excel的文件路径')
    .requiredOption('-s, --sheetName <name>', '输入一个sheet名')
    .requiredOption('-o, --output <file>', '输出 JSON 文件')
    .action(tojsonAction)

  program
    .command(COMMANDS.CREATE_BY_JSON)
    .description('根据json文件数据渲染word模板并输出')
    .requiredOption('-t, --template <file>', '输入word template文件的路径')
    .requiredOption('-j, --json <jsonPath>', '输入json文件的路径')
    .requiredOption('-o, --output <file>', '输出 目标word文件路径')
    .action(createByJsonAction)

  program
    .command(COMMANDS.PARSE_IMAGE)
    .description('根据json文件数据渲染图片word模板并输出')
    .requiredOption('-t, --template <file>', '输入图片 template文件的路径')
    .requiredOption('-j, --json <jsonPath>', '输入json文件的路径')
    .requiredOption('-o, --output <file>', '输出 目标word文件路径')
    .action(parseImageAction)

  program
    .command(COMMANDS.IMAGE_BY_DIR)
    .description('根据图片所有在文件夹生成word模板并输出')
    .requiredOption('-t, --template <file>', '输入图片 template文件的路径')
    .requiredOption('-d, --dir <dirPath>', '输入图片目录的路径')
    .requiredOption('-o, --output <file>', '输出目标word文件路径')
    .action(imageByDirAction)

  program
    .command(COMMANDS.CREATE_BY_XLSX)
    .description('根据json文件数据渲染word模板并输出')
    .requiredOption('-t, --template <file>', '输入word template文件的路径')
    .requiredOption('-x, --xlsxFile <xlsxPath>', '输入excel文件的路径')
    .requiredOption('-s, --sheetname  <name>', '输入excel文件sheet的名称')
    .requiredOption('-o, --output <file>', '输出目标word文件路径')
    .requiredOption('-d, --datakey <key>', '渲染对象的属性值')
    .action(createByXlsxAction)
  program
    .command(COMMANDS.MERGE_DATA)
    .description(
      '合并数组到一个对象中,使用方式merge --array <array1> --key <array2>'
    )
    .option('-k, --key <array>', '输入一个数组')
    .action(obj => {
      console.log(obj)
    })

  program.on('command:*', obj => {
    log.warn('未知命令：', `${obj[0]}不是一个可执行的命令\n`)
    log.info('帮助命令：-h --help')
    program.outputHelp()
  })

  program.parse(process.argv)
}

function tojsonAction({ input, sheetName, output }) {
  try {
    if (!pathExistsSync(input)) {
      log.error(`输入路径${input}的excel文件不存在`)
      process.exit(1)
    }
    const json = josnByXlsx(input, sheetName)
    if (isNoExtension(output)) {
      output = output + EXTENSION.json
    }
    fs.writeFileSync(output, JSON.stringify(json))
    log.info(`创建成功，输出路径为${output}`)
  } catch (error) {
    log.error(error.message)
  }
}

function createByJsonAction({ template, json, output }) {
  log.info('模板路径:', template)
  log.info('JSON路径:', json)
  try {
    if (!pathExistsSync(template)) {
      log.error(`输入路径${template}的模板文件不存在`)
      process.exit(1)
    }
    if (!pathExistsSync(json)) {
      log.error(`输入路径${json}的json数据文件不存在`)
      process.exit(1)
    }
    const data = JSON.parse(fs.readFileSync(json, 'utf-8'))
    renderAndWrite(template, data, output)
    log.info(`创建成功，输出路径为${output}`)
  } catch (error) {
    log.error(error.message)
  }
}
function parseImageAction({ template, json, output }) {
  log.info('模板路径:', template)
  log.info('JSON路径:', json)
  try {
    if (!pathExistsSync(template)) {
      log.error(`输入路径${template}的模板文件不存在`)
      process.exit(1)
    }
    if (!pathExistsSync(json)) {
      log.error(`输入路径${json}的json数据文件不存在`)
      process.exit(1)
    }
    const data = JSON.parse(fs.readFileSync(json, 'utf-8'))
    renderImage(template, data, output)
    log.info(`创建成功，输出路径为${output}`)
  } catch (error) {
    log.error(error.message)
  }
}

function imageByDirAction({ template, dir, output }) {
  try {
    if (!pathExistsSync(template)) {
      log.error(`输入路径${template}的模板文件不存在`)
      process.exit(1)
    }
    if (!pathExistsSync(dir)) {
      log.error(`输入路径${dir}的文件夹不存在`)
      process.exit(1)
    }
    const imagesAlt = globSync(`${dir}/*.{png,jpeg}`, {
      posix: true,
      nodir: true,
    })
    console.log('imagesAlt', imagesAlt)
    let data = {}
    for (const filePath of imagesAlt) {
      const parts = filePath.split('/')
      const filenameWithExt = parts.pop() // 获取文件名（包含扩展名）
      // 分离文件名和扩展名，只保留文件名部分
      const dotIndex = filenameWithExt.lastIndexOf('.')
            console.log('forof',filenameWithExt)
      const filename =
        dotIndex !== -1 ? filenameWithExt.slice(0, dotIndex) : filenameWithExt
      // 将文件名作为键，完整路径作为值存储
      data[filename] = filePath
    }
    // const data = { images: fs.readdirSync(dir) }
    console.log("data",data);
    renderImage(template, data, output)
    log.info(`创建成功，输出路径为${output}`)
  } catch (error) {
    log.error(error.message)
  }
}

function createByXlsxAction({
  template,
  xlsxFile,
  sheetname,
  output,
  datakey,
}) {
  log.info('模板路径:', template)
  log.info('xlsx路径:', xlsxFile)
  try {
    if (!pathExistsSync(template)) {
      log.error(`输入路径${template}的模板文件不存在`)
      process.exit(1)
    }
    if (!pathExistsSync(xlsxFile)) {
      log.error(`输入路径${xlsxFile}的xlsx文件不存在`)
      process.exit(1)
    }
    const json = josnByXlsx(xlsxFile, sheetname)
    const data = { [datakey]: json }
    renderAndWrite(template, data, output)
    log.info(`创建成功，输出路径为${output}`)
  } catch (error) {
    log.error(error.message)
  }
}

function renderAndWrite(template, data, output) {
  const context = fs.readFileSync(template, 'binary')
  const zip = new Pzip(context)
  const doc = new Docxtemplater(zip, {
    // modules: [new ImageModule(imageOptions)],
    parser: expressions,
    linebreaks: true,
  })
  doc.render(data)
  const generatedDocx = doc.getZip().generate({ type: 'nodebuffer' })
  if (isNoExtension(output)) {
    output = output + EXTENSION.docx
  }
  fs.writeFileSync(output, generatedDocx)
}

function renderImage(template, data, output) {
  const opts = {
    centered: false,
    getImage: function (tagValue, tagName) {
      console.log('tagName', tagName)
      return fs.readFileSync(tagValue)
    },
    getSize: function (img, tagValue, tagName) {
      console.log('getSize', { img, tagValue, tagName })
      return [150, 150]
    },
  }
  const imageModule = new ImageModule(opts)
  const context = fs.readFileSync(template, 'binary')
  const zip = new Pzip(context)
  const docx = new ImageDocxtemplater()
    .attachModule(imageModule)
    .loadZip(zip)
    .setData(data)
    .render()
  console.log('ImageDocxtemplater,rendered')
  const generatedDocx = docx.getZip().generate({ type: 'nodebuffer' })
  if (isNoExtension(output)) {
    output = output + EXTENSION.docx
  }
  fs.writeFileSync(output, generatedDocx)
}

function josnByXlsx(file, sheetName) {
  const workbook = XLSX.readFile(file)
  const worksheet = workbook.Sheets[sheetName]
  return XLSX.utils.sheet_to_json(worksheet)
}

function isNoExtension(filePath) {
  let reg = /\.[0-9a-z]+$/i
  return !reg.test(filePath)
}
module.exports = main
